package com.jfs.security.config;

import cn.hutool.core.util.ArrayUtil;
import com.jfs.security.filter.JwtAuthenticationFilter;
import com.jfs.security.properties.SecurityProperties;
import com.jfs.security.properties.SessionExecutorProperties;
import com.jfs.security.provider.JwtAuthenticationProvider;
import lombok.AllArgsConstructor;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

/**
 * @Description 安全配置
 * @E-mail cwm3412638@163.com
 * @Author cwm
 * @Date 2022/8/5
 */
@EnableWebSecurity // 开启WebSecurity模式
@AllArgsConstructor
@EnableConfigurationProperties(value = {SecurityProperties.class, SessionExecutorProperties.class})
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    private final UserDetailsService userDetailsService;
    private final SecurityProperties securityProperties;

    private final JwtAuthenticationFilter jwtAuthenticationFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors()
                .and()
                .csrf().disable()
                .authorizeRequests()
                // 跨域预检请求
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()
                //不拦截
                .antMatchers(ArrayUtil.toArray(securityProperties.getIgnoreUrls(), String.class)).permitAll()
                // 其他所有请求需要身份认证
                .anyRequest().authenticated()
                .and()
                //修改session策略 无状态应用 STATELESS 因为没用到session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
        //在密码认证过滤器之前添加自定义token校验过滤器
        http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }


    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 使用自定义登录身份认证组件
        JwtAuthenticationProvider jwtAuthenticationProvider = new JwtAuthenticationProvider(userDetailsService,new BCryptPasswordEncoder());
        //设置隐藏用户名不存在异常为true  不然无法捕获到用户不存在异常
        jwtAuthenticationProvider.setHideUserNotFoundExceptions(false);
        auth.authenticationProvider(jwtAuthenticationProvider);
    }
}
